//
//  MKAPIHttpRequestBase.h
//  MKAPI
//  http网络请求异步任务的基类。
//  Created by 苏尚进 on 2022/7/29.
//  Copyright © 2022 moon. All rights reserved.
//
/*
 在开发网络请求时，会有以下几个问题：
 1. 针对几十上百个网络请求，要如何规则代码？可想到的方案有
    1）在业务模块中，直接输入请求url，参数，然后回调中直接处理请求返回。
    2）对请求按功能进行模块划分，某一功能下的的所有请求都写在一个类中，每个请求对应该类的一个实例方法。该实例方法输入请求参数，设置完成回调。
    3）对请求按功能进行模块划分，为某一功能下的所有请求都建立一个基类，每个请求对应一个类（继承模块基类）。每个接口类，将请求参数，作为类的属性。对请求的响应数据进行二次加工，再设置到类的属性中。业务层调用时，设置类实例属性，在完成回调中，也是访问类的实例属性。
 2. 如何进行接口请求的内存管理？是请求自已管理内存，用完释放，还是需要由调用者持有？
 3. 业务流程中，需要按顺序发出多个请求，上一个请求结束之后，才能发起下一个请求，如何对此类请求进行链式管理？
    如果采用block回调，则当请求链太长时，block的深度会太长，代码不好维护。针对该请求链，要怎么进行取消操作？
 4. 考虑场景：所有的请求，都有一个前置请求，该前置请求只能发一次，不可以并发。当有多个请求要发送时，如何管理前置请求，满足前置请求只发送一次？
 5. 所有请求都需要上送公共的参数，以及进行统一的响应结果处理，错误处理，要如何进行实现？
 
 
 针对以上问题，建议方案为：
 1. 构建一层网络接口层，为每一个网络请求，建立一个类（如登录请求login，则建立类MKAPILogin）。
 所有的网络请求类，都继承网络接口基类（如MKAPIBase)。在基类中，进行请求公共参数处理，统一的响应结果处理和错误处理。
 2. 该网络接口基类，通过全局的网络请求会话对象，管理生命周期。业务层只需要实例化接口对象，设置好参数，以及回调方法，调用发送即可。
 3. 网络接口基类，添加请求依赖功能，用于实现请求链。添加cancel取消方法，取消时，检测请求链式依赖，同步取消整个请求链。
 4. 添加一个全局的网络请求会话实例，该实例持有所有的未完成的网络请求，并提供线程安全的网络请求查询功能。
    针对前置请求场景，可以在实例化前置请求之前，查询是否已经有存在的前置请求。如果已有，则直接使用会话中的前置请求。
 5. 可以将该请求的所有文档，以及请求的url，header，参数，响应，错误情况等日志，都写在请求类的注释中，方便后人维护请求实现。
 */

#import <Foundation/Foundation.h>
#import "MKAPIHttpFile.h"
#import "MKAPITask.h"
#import "MKAPIDictionary.h"
#import "MKAPIRequestParam.h"

typedef enum : NSUInteger {
    MKAPIHttpRequestTypeData,//获取、提交数据
    MKAPIHttpRequestTypeDownload,//下载文件
    MKAPIHttpRequestTypeUpload,//上传文件
} MKAPIHttpRequestType;

NS_ASSUME_NONNULL_BEGIN
@interface MKAPIHttpRequestBase : MKAPITask{
    @protected
    NSURLRequest *_request;
    NSHTTPURLResponse *_response;
    NSData *_responseData;
    NSURL *_responseFile;
}
@property(nonatomic,assign) MKAPIHttpRequestType requestType;//获取数据、上传文件、下载文件
@property(nonatomic,strong,nullable) __kindof MKAPIRequestParam *requestParam;//请求参数
@property(nonatomic,readonly,nullable) NSURLRequest *request;//要发出去的请求对象
//返回对象
@property(nonatomic,readonly,nullable) NSHTTPURLResponse *response;
@property(nonatomic,readonly,nullable) NSData *responseData;//响应返回的数据
@property(nonatomic,strong,nullable) NSURL *responseFile;//响应返回的下载文件路径

/// 输出request日志
/// - Parameter block: 扩展日记的执行block
+ (NSString *)requestDescriptionWithRequest:(nullable __kindof MKAPIHttpRequestBase *)request requestParam:(nullable __kindof MKAPIRequestParam *)requestParam customBlock:(NSString *(^_Nullable)(__kindof MKAPIHttpRequestBase *request))block;

/// 输出response日志
/// - Parameter block: 扩展日记的执行block
+ (NSString *)responseDescriptionWithRequest:(nullable __kindof MKAPIHttpRequestBase *)request requestParam:(nullable __kindof MKAPIRequestParam *)requestParam customBlock:(NSString *(^_Nullable)(__kindof MKAPIHttpRequestBase *request))block;
@end

@interface MKAPIHttpRequestBase (response)
@property(nonatomic,readonly,nullable) NSString *responseString;//返回utf8编码的字符串
@property(nonatomic,readonly,nullable) id responseJson;//获取json格式的返回
@property(nonatomic,readonly,nullable) NSDictionary *responseJsonDict;//获取json字典格式的返回
@property(nonatomic,readonly,nullable) NSArray *responseJsonArray;//获取json数组格式的返回
@property(nonatomic,readonly,nullable) UIImage *responseImage;//获取图片返回
@end

NS_ASSUME_NONNULL_END
